// 顶部头文件：补充标准库
#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>

#include "./../../inc/homepage.h"
#include "./../../inc/msg_popup.h"
#include "./../../inc/cJSON.h"
#include "./../../inc/user_event.h"
#include "./../../inc/tcp.h"
#include "./../../inc/weather.h"

typedef struct
{
    char date[16];        // 日期
    char temperature[16]; // 温度范围
    char weather[16];     // 天气状况
    char direct[16];      // 风向
} DayWeather;

typedef struct
{
    DayWeather daily_data[5]; // 近5天天气数据（无类型错误）
    uint8_t day_count;        // 实际有效天数（最多5天）
    char city[32];            // 城市名称
    int is_valid;             // 数据有效性标记（1=有效，0=无效）
} GlobalWeatherData;

GlobalWeatherData g_global_weather_data = {0};                       // 全局解析后天气数据
pthread_mutex_t g_weather_mutex         = PTHREAD_MUTEX_INITIALIZER; // 保护全局数据的互斥锁

// WeatherDialogCtx 结构体
typedef struct
{
    lv_obj_t * dialog;        // 弹窗主容器
    lv_obj_t * overlay;       // 半透明背景层
    lv_obj_t * loading_label; // 正在加载提示
    lv_obj_t * refresh_btn;   // 刷新按钮
    DayWeather daily_data[5]; // 近5天天气数据
    uint8_t day_count;        // 实际天数
    char city[32];            // 城市名称
} WeatherDialogCtx;

static WeatherDialogCtx g_weather_ctx = {0};

// 辅助函数：从原始JSON字符串解析出天气数据，存入临时结构体
static int parse_raw_json_to_temp(const char * raw_json, GlobalWeatherData * temp_data)
{
    if(raw_json == NULL || temp_data == NULL) {
        printf("解析失败：输入参数为空\n");
        return -1;
    }

    // 初始化临时数据
    memset(temp_data, 0, sizeof(GlobalWeatherData));
    temp_data->is_valid = 0;

    // 解析原始JSON
    cJSON * root = cJSON_Parse(raw_json);
    if(root == NULL) {
        printf("JSON解析失败: %s\n", cJSON_GetErrorPtr());
        return -1;
    }

    // 提取城市名称
    cJSON * result = cJSON_GetObjectItem(root, "result");
    if(result != NULL) {
        // 解析城市
        cJSON * city_json = cJSON_GetObjectItem(result, "city");
        if(city_json != NULL && cJSON_IsString(city_json)) {
            strncpy(temp_data->city, city_json->valuestring, sizeof(temp_data->city) - 1);
        }

        // 解析近5天天气数组
        cJSON * future = cJSON_GetObjectItem(result, "future");
        if(future != NULL && cJSON_IsArray(future)) {
            temp_data->day_count = cJSON_GetArraySize(future);
            if(temp_data->day_count > 5) temp_data->day_count = 5; // 限制最多5天

            // 遍历提取每天数据
            for(uint8_t i = 0; i < temp_data->day_count; i++) {
                cJSON * day_item = cJSON_GetArrayItem(future, i);
                if(day_item == NULL) continue;

                // 日期
                cJSON * date = cJSON_GetObjectItem(day_item, "date");
                if(date != NULL && cJSON_IsString(date)) {
                    strncpy(temp_data->daily_data[i].date, date->valuestring,
                            sizeof(temp_data->daily_data[i].date) - 1);
                }
                // 温度
                cJSON * temp = cJSON_GetObjectItem(day_item, "temperature");
                if(temp != NULL && cJSON_IsString(temp)) {
                    strncpy(temp_data->daily_data[i].temperature, temp->valuestring,
                            sizeof(temp_data->daily_data[i].temperature) - 1);
                }
                // 天气状况
                cJSON * weather = cJSON_GetObjectItem(day_item, "weather");
                if(weather != NULL && cJSON_IsString(weather)) {
                    strncpy(temp_data->daily_data[i].weather, weather->valuestring,
                            sizeof(temp_data->daily_data[i].weather) - 1);
                }
                // 风向
                cJSON * direct = cJSON_GetObjectItem(day_item, "direct");
                if(direct != NULL && cJSON_IsString(direct)) {
                    strncpy(temp_data->daily_data[i].direct, direct->valuestring,
                            sizeof(temp_data->daily_data[i].direct) - 1);
                }
            }
        }
    }

    // 标记数据有效
    temp_data->is_valid = 1;
    cJSON_Delete(root);
    return 0;
}

// 处理服务器天气响应：先解析原始JSON，再线程安全保存解析后的数据
void handle_weather_response(const char * raw_json)
{
    // 步骤1：校验原始JSON输入
    if(raw_json == NULL || strlen(raw_json) == 0) {
        printf("警告：服务器返回的JSON为空\n");
        return;
    }

    // 步骤2：解析原始JSON到临时结构体（非临界区，无需加锁）
    GlobalWeatherData temp_data;
    if(parse_raw_json_to_temp(raw_json, &temp_data) != 0) {
        printf("警告：原始JSON解析失败，不更新全局数据\n");
        return;
    }

    // 步骤3：加锁，线程安全保存到全局变量
    if(pthread_mutex_lock(&g_weather_mutex) != 0) {
        perror("加锁失败：handle_weather_response");
        return;
    }

    // 拷贝临时数据到全局变量（结构化数据直接赋值，无需malloc）
    memcpy(&g_global_weather_data, &temp_data, sizeof(GlobalWeatherData));
    printf("成功保存解析后数据：城市=%s，有效天数=%d\n", g_global_weather_data.city, g_global_weather_data.day_count);

    // 步骤4：解锁
    if(pthread_mutex_unlock(&g_weather_mutex) != 0) {
        perror("解锁失败：handle_weather_response");
    }
}

// -------------------------- 4. 修改：解析函数（直接读取全局结构化数据） --------------------------
// 从全局结构化变量中读取数据，无需再解析JSON
static void parse_weather_json(DayWeather * daily_data, uint8_t * day_count, char * city)
{
    // 初始化输出参数
    *day_count = 0;
    memset(city, 0, 32);
    memset(daily_data, 0, sizeof(DayWeather) * 5);

    // 加锁访问全局数据
    if(pthread_mutex_lock(&g_weather_mutex) != 0) {
        perror("加锁失败：parse_weather_json");
        return;
    }

    // 若数据有效，拷贝到输出参数
    if(g_global_weather_data.is_valid == 1) {
        strncpy(city, g_global_weather_data.city, 31);
        *day_count = g_global_weather_data.day_count;
        memcpy(daily_data, g_global_weather_data.daily_data, sizeof(DayWeather) * g_global_weather_data.day_count);
    } else {
        printf("全局天气数据无效，无法读取\n");
    }

    // 解锁
    if(pthread_mutex_unlock(&g_weather_mutex) != 0) {
        perror("解锁失败：parse_weather_json");
    }
}

// -------------------------- 以下原有函数（create_daily_container、clear_weather_cards等）保持不变
// --------------------------
static void create_daily_container(lv_obj_t * parent, const DayWeather * day, int y_offset)
{
    lv_obj_t * container = lv_obj_create(parent);
    lv_obj_set_pos(container, 5, y_offset);
    lv_obj_set_size(container, 480, 40);
    lv_obj_set_style_bg_color(container, lv_color_hex(0xFFFFFF), 0);
    lv_obj_set_style_border_width(container, 1, 0);
    lv_obj_set_style_border_color(container, lv_color_hex(0xEEEEEE), 0);
    lv_obj_clear_flag(container, LV_OBJ_FLAG_SCROLLABLE);

    // 日期标签
    lv_obj_t * date_lab = lv_label_create(container);
    lv_label_set_text(date_lab, day->date);
    lv_obj_align(date_lab, LV_ALIGN_CENTER, -170, 0);
    lv_obj_set_style_text_font(date_lab, &SourceHanSansCN_Bold_20, 0);
    lv_obj_set_style_text_color(date_lab, lv_color_hex(0x333333), 0);

    // 天气状况标签
    lv_obj_t * weather_lab = lv_label_create(container);
    lv_label_set_text(weather_lab, day->weather);
    lv_obj_align(weather_lab, LV_ALIGN_CENTER, -40, 0);
    lv_obj_set_style_text_font(weather_lab, &SourceHanSansCN_Bold_20, 0);
    lv_obj_set_style_text_color(weather_lab, lv_color_hex(0x666666), 0);

    // 温度标签
    lv_obj_t * temp_lab = lv_label_create(container);
    lv_label_set_text(temp_lab, day->temperature);
    lv_obj_align(temp_lab, LV_ALIGN_CENTER, 70, 0);
    lv_obj_set_style_text_font(temp_lab, &SourceHanSansCN_Bold_20, 0);
    lv_obj_set_style_text_color(temp_lab, lv_color_hex(0x666666), 0);

    // 风向标签
    lv_obj_t * direct_lab = lv_label_create(container);
    lv_label_set_text(direct_lab, day->direct);
    lv_obj_align(direct_lab, LV_ALIGN_CENTER, 175, 0);
    lv_obj_set_style_text_font(direct_lab, &SourceHanSansCN_Bold_20, 0);
    lv_obj_set_style_text_color(direct_lab, lv_color_hex(0x666666), 0);
}

static void clear_weather_cards(void)
{
    if(g_weather_ctx.dialog == NULL) return;

    lv_obj_t * child = lv_obj_get_child(g_weather_ctx.dialog, NULL);
    while(child != NULL) {
        lv_obj_t * next_child = lv_obj_get_child(g_weather_ctx.dialog, child);
        if(lv_obj_get_width(child) == 480 && lv_obj_get_height(child) == 40) {
            lv_obj_del(child);
        }
        child = next_child;
    }
}

static void refresh_weather(void)
{
    if(g_weather_ctx.loading_label != NULL) {
        lv_obj_clear_flag(g_weather_ctx.loading_label, LV_OBJ_FLAG_HIDDEN);
    }

    clear_weather_cards();
    parse_weather_json(g_weather_ctx.daily_data, &g_weather_ctx.day_count, g_weather_ctx.city);

    lv_obj_t * title = lv_obj_get_child(g_weather_ctx.dialog, NULL);
    if(title != NULL) {
        lv_label_set_text_fmt(title, "%s 近5天天气预报", g_weather_ctx.city);
    }

    if(g_weather_ctx.day_count > 0) {
        if(g_weather_ctx.loading_label != NULL) {
            lv_obj_add_flag(g_weather_ctx.loading_label, LV_OBJ_FLAG_HIDDEN);
        }

        for(uint8_t i = 0; i < g_weather_ctx.day_count; i++) {
            create_daily_container(g_weather_ctx.dialog, &g_weather_ctx.daily_data[i], 50 + i * 50);
        }
    }
}

static void on_refresh_btn_click(lv_event_t * e)
{
    cJSON * root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "type", "weather");
    char * json_str = cJSON_PrintUnformatted(root);

    if(json_str != NULL) {
        send_message_to_server(&server_info, json_str);
        free(json_str);
        refresh_weather();
    }

    cJSON_Delete(root);
}

static void close_weather_popup(void)
{
    if(g_weather_ctx.dialog) {
        lv_obj_del(g_weather_ctx.dialog);
        g_weather_ctx.dialog = NULL;
    }
    if(g_weather_ctx.overlay) {
        lv_obj_del(g_weather_ctx.overlay);
        g_weather_ctx.overlay = NULL;
    }

    g_weather_ctx.loading_label = NULL;
    g_weather_ctx.refresh_btn   = NULL;
    g_weather_ctx.day_count     = 0;
    memset(g_weather_ctx.daily_data, 0, sizeof(g_weather_ctx.daily_data));
    memset(g_weather_ctx.city, 0, sizeof(g_weather_ctx.city));
}

static void on_overlay_click(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    if(target == g_weather_ctx.overlay) {
        close_weather_popup();
    }
}

void show_weather_popup(void)
{
    close_weather_popup();
    parse_weather_json(g_weather_ctx.daily_data, &g_weather_ctx.day_count, g_weather_ctx.city);

    g_weather_ctx.overlay = lv_obj_create(lv_scr_act());
    lv_obj_set_size(g_weather_ctx.overlay, LV_HOR_RES, LV_VER_RES);
    lv_obj_set_style_bg_color(g_weather_ctx.overlay, lv_color_black(), 0);
    lv_obj_set_style_bg_opa(g_weather_ctx.overlay, LV_OPA_50, 0);
    lv_obj_set_style_border_width(g_weather_ctx.overlay, 0, 0);
    lv_obj_set_style_radius(g_weather_ctx.overlay, 0, 0);
    lv_obj_clear_flag(g_weather_ctx.overlay, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_add_event_cb(g_weather_ctx.overlay, on_overlay_click, LV_EVENT_CLICKED, NULL);

    g_weather_ctx.dialog = lv_obj_create(g_weather_ctx.overlay);
    lv_obj_set_size(g_weather_ctx.dialog, 530, 390);
    lv_obj_align(g_weather_ctx.dialog, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_bg_color(g_weather_ctx.dialog, lv_color_hex(0xF5F5F5), 0);
    lv_obj_set_style_radius(g_weather_ctx.dialog, 10, 0);
    lv_obj_clear_flag(g_weather_ctx.dialog, LV_OBJ_FLAG_SCROLLABLE);

    lv_obj_t * title = lv_label_create(g_weather_ctx.dialog);
    lv_label_set_text_fmt(title, "%s 近5天天气预报", g_weather_ctx.city);
    lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10);
    lv_obj_set_style_text_font(title, &SourceHanSansCN_Bold_20, 0);
    lv_obj_set_style_text_color(title, lv_color_hex(0x333333), 0);

    g_weather_ctx.loading_label = lv_label_create(g_weather_ctx.dialog);
    lv_label_set_text(g_weather_ctx.loading_label, "正在加载天气数据...");
    lv_obj_align(g_weather_ctx.loading_label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_text_font(g_weather_ctx.loading_label, &SourceHanSansCN_Bold_20, 0);
    lv_obj_set_style_text_color(g_weather_ctx.loading_label, lv_color_hex(0x999999), 0);

    if(g_weather_ctx.day_count > 0) {
        lv_obj_add_flag(g_weather_ctx.loading_label, LV_OBJ_FLAG_HIDDEN);
        for(uint8_t i = 0; i < g_weather_ctx.day_count; i++) {
            create_daily_container(g_weather_ctx.dialog, &g_weather_ctx.daily_data[i], 50 + i * 50);
        }
    }

    g_weather_ctx.refresh_btn = lv_btn_create(g_weather_ctx.dialog);
    lv_obj_set_size(g_weather_ctx.refresh_btn, 100, 35);
    lv_obj_align(g_weather_ctx.refresh_btn, LV_ALIGN_BOTTOM_MID, 0, -15);
    lv_obj_set_style_bg_color(g_weather_ctx.refresh_btn, lv_color_hex(0x409EFF), 0);
    lv_obj_set_style_radius(g_weather_ctx.refresh_btn, 6, 0);

    lv_obj_t * btn_lab = lv_label_create(g_weather_ctx.refresh_btn);
    lv_label_set_text(btn_lab, "刷新数据");
    lv_obj_center(btn_lab);
    lv_obj_set_style_text_color(btn_lab, lv_color_hex(0xFFFFFF), 0);
    lv_obj_set_style_text_font(btn_lab, &SourceHanSansCN_Bold_20, 0);

    lv_obj_add_event_cb(g_weather_ctx.refresh_btn, on_refresh_btn_click, LV_EVENT_CLICKED, NULL);
}

void weather_init(void)
{
    g_weather_ctx.dialog        = NULL;
    g_weather_ctx.overlay       = NULL;
    g_weather_ctx.loading_label = NULL;
    g_weather_ctx.refresh_btn   = NULL;
    g_weather_ctx.day_count     = 0;
    memset(g_weather_ctx.daily_data, 0, sizeof(g_weather_ctx.daily_data));
    memset(g_weather_ctx.city, 0, sizeof(g_weather_ctx.city));

    // 初始化全局结构化数据
    memset(&g_global_weather_data, 0, sizeof(GlobalWeatherData));
    g_global_weather_data.is_valid = 0;
}